﻿using System;

using GTM = Gadgeteer.Modules;
using GTI = Gadgeteer.Interfaces;

namespace Gadgeteer.Modules.GHIElectronics
{
    // -- CHANGE FOR MICRO FRAMEWORK 4.2 --
    // If you want to use Serial, SPI, or DaisyLink (which includes GTI.SoftwareI2C), you must do a few more steps
    // since these have been moved to separate assemblies for NETMF 4.2 (to reduce the minimum memory footprint of Gadgeteer)
    // 1) add a reference to the assembly (named Gadgeteer.[interfacename])
    // 2) in GadgeteerHardware.xml, uncomment the lines under <Assemblies> so that end user apps using this module also add a reference.

    /// <summary>
    /// A XBee module for Microsoft .NET Gadgeteer
    /// </summary>
    public class XBee : GTM.Module
    {
        /// <summary>
        /// Gets the <see cref="T:Microsoft.Gadgeteer.Interfaces.Serial"/> device associated with this instance.
        /// </summary>
        public GTI.Serial SerialLine
        {
            get
            {
                if (_SerialLine == null)
                {
                    Configure(115200, GTI.Serial.SerialParity.None, GTI.Serial.SerialStopBits.One, 8);
                }
                return _SerialLine;
            }
            private set
            {
                _SerialLine = value;
            }
        }

        private GTI.Serial _SerialLine = null;

        private Socket socket;

        // Note: A constructor summary is auto-generated by the doc builder.
        /// <summary></summary>
        /// <param name="socketNumber">The socket that this module is plugged in to.</param>
        /// <remarks>
        /// The function <see cref="Configure"/> can be called to configure the <see cref="SerialLine"/> before it is used.  
        /// If it is not called before first use, then the following defaults will be used and cannot be changed afterwards:
        /// <list type="bullet">
        ///  <item>Baud Rate - 115200</item>
        ///  <item>Parity - <see cref="T:Microsoft.Gadgeteer.Interfaces.Serial.SerialParity">SerialParity.None</see></item>
        ///  <item>Stop Bits - <see cref="T:Microsoft.Gadgeteer.Interfaces.Serial.SerialStopBits">SerialStopBits.One</see></item>
        ///  <item>Data Bits - 8</item>
        /// </list>
        /// </remarks>
        public XBee(int socketNumber)
        {
            // This finds the Socket instance from the user-specified socket number.  
            // This will generate user-friendly error messages if the socket is invalid.
            // If there is more than one socket on this module, then instead of "null" for the last parameter, 
            // put text that identifies the socket to the user (e.g. "S" if there is a socket type S)
            socket = Socket.GetSocket(socketNumber, true, this, null);

            char[] types = { 'K', 'U' };
            socket.EnsureTypeIsSupported(types, this);
        }

        /// <summary>
        /// Configures this serial line.  This should be called at most once.
        /// </summary>
        /// <param name="baudRate">The baud rate.</param>
        /// <param name="parity">A value from the <see cref="T:Microsoft.Gadgeteer.Interfaces.Serial.SerialParity"/> enumeration that specifies the parity.</param>
        /// <param name="stopBits">A value from the <see cref="T:Microsoft.Gadgeteer.Interfaces.Serial.SerialStopBits"/> enumeration that specifies the number of stop bits.</param>
        /// <param name="dataBits">The number of data bits.</param>
        public void Configure(int baudRate, GTI.Serial.SerialParity parity, GTI.Serial.SerialStopBits stopBits, int dataBits)
        {
            if (_SerialLine != null)
            {
                throw new Exception("UsbSerial.Configure can only be called once");
            }
            // TODO: check if HW flow control should be used
            _SerialLine = new GTI.Serial(socket, baudRate, parity, stopBits, dataBits, GTI.Serial.HardwareFlowControl.NotRequired, this);
        }
    }
}